/*
    This source file is part of GeNa project.
    Copyright © GeNa project 2008
    For the latest info, see http://code.google.com/p/genaproject/ or  http://lumpyproject.forums-rpg.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Foobar is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Foobar.  If not, see <http://www.gnu.org/licenses/>. */

#ifndef WINDOWS_MANAGER_SERIALIZATION_H_INCLUDED
#define WINDOWS_MANAGER_SERIALIZATION_H_INCLUDED

#include <boost/serialization/nvp.hpp>
#include <boost/archive/basic_archive.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/string.hpp>
using namespace boost::serialization;

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/construct.hpp>
#include <boost/lambda/casts.hpp>
#include <boost/lambda/if.hpp>
#include <boost/ref.hpp>
#include <boost/function.hpp>
using namespace boost::lambda;

#include "windows_manager.h"
#include "application.h"


template<class Archive> void WindowsManager::Node::serialize(Archive & ar, const unsigned int version)
{
    if( parent)
    {

        if( Archive::is_saving::value)
        {
            int mode = (splitter->GetSplitMode() == wxSPLIT_HORIZONTAL) ? MODE_HORIZONTAL : MODE_VERTICAL;
            ar & BOOST_SERIALIZATION_NVP(mode);

            int pos = splitter->GetSashPosition();
            ar & BOOST_SERIALIZATION_NVP(pos);
        }
        else
        {
            int mode;
            float pos;
            ar & BOOST_SERIALIZATION_NVP(mode);
            ar & BOOST_SERIALIZATION_NVP(pos);

            appInstance->callFunction( (var(splitter) = bind(new_ptr<WindowsManager::Splitter>(), parent->splitter ? parent->splitter : parent->parentWnd),
                                        if_then_else( constant(mode == MODE_VERTICAL),
                                                      bind( &WindowsManager::Splitter::SetSplitMode, var(splitter), wxSPLIT_VERTICAL),
                                                      bind( &WindowsManager::Splitter::SetSplitMode, var(splitter), wxSPLIT_HORIZONTAL)),
                                        bind(&WindowsManager::Node::updateLink,parent),
                                        bind( &WindowsManager::Splitter::SetSashPosition, var(splitter), pos, true)
                                        ));
            //The main thread do :
            //splitter = new Splitter( parent->splitter ? parent->splitter : parent->parentWnd);
            //if( mode == MODE_VERTICAL)
            //    splitter->SetSplitMode(wxSPLIT_VERTICAL);
            //else
            //    splitter->SetSplitMode(wxSPLIT_HORIZONTAL);
            //parent->updateLink();
            //splitter->SetSashPosition(pos,true);
            splitter->mNode = this;
        }

        wxMilliSleep(100);
    }

    if( Archive::is_saving::value)
    {
        int isLSplitter = (bool)leftNode;
        int isRSplitter = (bool)rightNode;

        ar & BOOST_SERIALIZATION_NVP(isLSplitter);
        ar & BOOST_SERIALIZATION_NVP(isRSplitter);

        bool isEmpty = (bool)leftLeaf && (bool)leftNode;
        if( !parent)
            ar & BOOST_SERIALIZATION_NVP(isEmpty);

        if( !isEmpty)
        {
            if( isLSplitter)
                ar & make_nvp("left", *leftNode);
            else
                ar & make_nvp("left", *leftLeaf);
        }

        if( parent)
        {
            if( isRSplitter)
                ar & make_nvp("right", *rightNode);
            else
                ar & make_nvp("right", *rightLeaf);
        }
    }
    else
    {
        int isLSplitter;
        int isRSplitter;

        ar & BOOST_SERIALIZATION_NVP(isLSplitter);
        ar & BOOST_SERIALIZATION_NVP(isRSplitter);

        bool isEmpty = false;
        if( !parent)
            ar & BOOST_SERIALIZATION_NVP(isEmpty);

        if( !isEmpty)
        {
            if( isLSplitter)
            {
                leftNode = new Node;
                leftNode->parent = this;
                ar & make_nvp("left", *leftNode);
            }
            else
            {
                leftLeaf = new Leaf;
                leftLeaf->parent = this;
                ar & make_nvp("left", *leftLeaf);
            }
        }

        if( parent)
        {
            if( isRSplitter)
            {
                rightNode = new Node;
                rightNode->parent = this;
                ar & make_nvp("right", *rightNode);
            }
            else
            {
                rightLeaf = new Leaf;
                rightLeaf->parent = this;
                ar & make_nvp("right", *rightLeaf);
            }
        }
        else
            rightLeaf = NULL;
    }
}

template<class Archive> void WindowsManager::Leaf::serialize(Archive & ar, const unsigned int version)
{

    std::string name;

    if( Archive::is_saving::value)
    {
        name = wnd->getName();
        ar & BOOST_SERIALIZATION_NVP(name);
        WindowsFactoryInstance.saveWindow( wnd, &ar);
    }
    else
    {
        ar & BOOST_SERIALIZATION_NVP(name);

        appInstance->callFunction(var(wnd) = bind( &WindowsFactory::createWindow<void>, boost::ref(WindowsFactoryInstance), name, parent->splitter ? parent->splitter : parent->parentWnd, &ar));

        if( !wnd)
        {
            void* null = NULL;
            appInstance->callFunction(var(wnd) = bind( &WindowsFactory::createWindow<void>, boost::ref(WindowsFactoryInstance), std::string("UnknowWindow"), parent->splitter ? parent->splitter : parent->parentWnd, null));
        }

        appInstance->callFunction(bind( &WindowsManager::Node::updateLink, parent));
        wxMilliSleep(100);
    }
}

#endif // WINDOWS_MANAGER_SERIALIZATION_H_INCLUDED
